package procimagem;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

public class Histograma {

	public final int LARG_DESENHO = 300;
	public final int ALT_DESENHO = 400;

	private ImagemPGM imagem;

	private ImagemPGM novaImagem;

	private int[] mapa_pixel;

	private float[] mapa_prk;

	private float[] mapa_sk;

	private int[] novo_k;

	private int[] novo_mapa;

	private float[] mapa_pr_sk;

	private BufferedImage grafico;

	private BufferedImage novoGrafico;

	public Histograma(ImagemPGM imagem) {
		this.imagem = imagem;
		this.novaImagem = new ImagemPGM(imagem.largura, imagem.altura,
				imagem.maxValue, imagem.pixels);
		this.obtemDados();
		this.obtemPrk();
		this.obtemSk();
		this.obtemNovoK();
		this.obtemNovoMapa();
		this.obtemPrSk();
		this.equalizaImagem();
	}

	private void obtemDados() {
		this.mapa_pixel = new int[imagem.maxValue + 1];
		for (int i = 0; i < imagem.largura; i++) {
			for (int j = 0; j < imagem.altura; j++) {
				int k = imagem.pixels[i][j];
				this.mapa_pixel[k] = this.mapa_pixel[k] + 1;
			}
		}
	}

	private void obtemPrk() {
		this.mapa_prk = new float[imagem.maxValue + 1];
		float quant = imagem.largura * imagem.altura;
		float a = 0.0F;
		for (int i = 0; i < this.mapa_pixel.length; i++) {

			this.mapa_prk[i] = this.mapa_pixel[i] / quant;
			a += this.mapa_prk[i];
		}
	}

	private void obtemSk() {
		this.mapa_sk = new float[imagem.maxValue + 1];

		float a = 0F;
		for (int i = 0; i < this.mapa_sk.length; i++) {
			 a += this.mapa_prk[i];
			this.mapa_sk[i] = a;
		}
	}

	private void obtemNovoK() {
		this.novo_k = new int[imagem.maxValue + 1];
		for (int i = 0; i < this.novo_k.length; i++) {
			this.novo_k[i] = Math.round(this.mapa_sk[i] * imagem.maxValue);
		}
	}

	private void obtemNovoMapa() {
		this.novo_mapa = new int[imagem.maxValue + 1];
		for (int i = 0; i < this.novo_mapa.length; i++) {
			int index = this.novo_k[i];
			this.novo_mapa[index] = this.mapa_pixel[i]
					+ this.novo_mapa[index];
		}
	}

	private void obtemPrSk() {
		this.mapa_pr_sk = new float[imagem.maxValue + 1];
		float quant = imagem.largura * imagem.altura;
		for (int i = 0; i < this.mapa_pr_sk.length; i++) {
			this.mapa_pr_sk[i] = this.novo_mapa[i] / quant;
		}
	}

	public void desenhaGrafico() {
		this.grafico = new BufferedImage(this.LARG_DESENHO, this.ALT_DESENHO,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g = this.grafico.createGraphics();
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, this.LARG_DESENHO, this.ALT_DESENHO);
		g.setColor(Color.WHITE);
		g.drawLine(10, 380, 290, 380);
		g.drawLine(20, 390, 20, 10);
		g.setColor(Color.YELLOW);
		for (int i = 0; i < this.mapa_prk.length; i++) {
			int x = 20 + i;
			int y = 380 - Math.round(this.mapa_prk[i] * 4000);
			g.drawLine(x, 380, x, y);
		}
	}

	public void desenhaEqualizado() {
		this.novoGrafico = new BufferedImage(this.LARG_DESENHO,
				this.ALT_DESENHO, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = this.novoGrafico.createGraphics();
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, this.LARG_DESENHO, this.ALT_DESENHO);
		g.setColor(Color.WHITE);
		g.drawLine(10, 380, 290, 380);
		g.drawLine(20, 390, 20, 10);
		g.setColor(Color.YELLOW);
		for (int i = 0; i < this.mapa_pr_sk.length; i++) {
			int x = 20 + i;
			int y = 380 - Math.round(this.mapa_pr_sk[i] * 4000);
			g.drawLine(x, 380, x, y);
		}
	}

	public BufferedImage getGrafico() {
		return this.grafico;
	}

	public BufferedImage getGraficoEqualizado() {
		return this.novoGrafico;
	}

	private void equalizaImagem() {
		for (int i = 0; i < this.novaImagem.largura; i++) {
			for (int j = 0; j < this.novaImagem.altura; j++) {
				this.novaImagem.pixels[i][j] = this.novo_k[this.novaImagem.pixels[i][j]];
			}
		}
	}

	public ImagemPGM getImagemEqualizada(){
		return this.novaImagem;
	}

}
